﻿package net.wangit.jdbc.executable;

import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;

import net.wangit.framework.debug.Recorder;
import net.wangit.jdbc.DBImplementor;
import net.wangit.jdbc.JDBCException;
import net.wangit.jdbc.database.Database;
import net.wangit.jdbc.table.Column;
import net.wangit.jdbc.table.TableMeta;
import net.wangit.jdbc.util.JDBCExceptionReporter;


public class InsertRow extends AbstractColumnRow implements Executable {

	private static final long serialVersionUID = 1L;

	public InsertRow() {
	}

	public void execute(DBImplementor db, TableMeta meta, int count[],
			String unitId) throws JDBCException {
		List<Column> insertableColumns;
		String sql;
		PreparedStatement ps;
		Database database = db.getJDBCSettings().getDatabase();
		List<Column> primaryKeyColumns = meta.getPrimaryKey().getColumns();
		boolean isDuplicate = ConstraintChecker.isDuplicate(db, meta
				.getQualifiedName(db), primaryKeyColumns, this);
		if (isDuplicate) {
			throw new ConstraintException(ConstraintChecker
					.getConstraintExceptionMessage(primaryKeyColumns, this,
							unitId));
		}
		insertableColumns = getInsertableColumns(meta);
		sql = SQLUtil.toInsertStatement(meta.getQualifiedName(db),
				insertableColumns);
		ps = null;
		try {
			ps = db.getBatcher().prepareStatement(sql);
			for (int i = 0; i < insertableColumns.size(); i++) {
				Column column = insertableColumns.get(i);
				column.getSqlType(database).set(ps, getColumnValue(column),
						i + 1);
			}

			count[0] += ps.executeUpdate();
		} catch (SQLException sqle) {
			JDBCExceptionReporter.logExceptions(sqle);
			throw new JDBCException((new StringBuilder("could not insert: "))
					.append(sql).toString(), sqle);
		} finally {
			try {
				db.getBatcher().closeStatement(ps);
			} catch (SQLException sqle) {
				throw new JDBCException("could not close statement", sqle);
			}
		}
		Recorder.countInsert();
	}

	private List<Column> getInsertableColumns(TableMeta meta) {
		List<Column> result = new ArrayList<Column>();
		List<Column> primaryKeyColumns = meta.getPrimaryKey().getColumns();
		result.addAll(primaryKeyColumns);
		List<Column> columns = meta.getColumns();
		for (int i = 0; i < columns.size(); i++) {
			Column column = columns.get(i);
			if (column.isAutoByDB()) {
				result.remove(column);
			} else if (!result.contains(column)
					&& (get(column.getName()) != null || column
							.isEnabledByGenerator(this))) {
				result.add(column);
			}
		}

		return result;
	}

	public boolean isInsertRow() {
		return true;
	}

	public boolean isUpdateRow() {
		return false;
	}

	public boolean isDeleteRow() {
		return false;
	}
}
